#ifndef __HTHREADPOOL_QUEUE_ATOMICPRIORITYQUEUE_H__
#define __HTHREADPOOL_QUEUE_ATOMICPRIORITYQUEUE_H__

#include <queue>
#include "QueueObject.h"
#include "ThreadPoolDefine.h"
#include "UMemory.h"

HTHREADPOOL_NAMESPACE_BEGIN

    template<typename T>
    class AtomicPriorityQueue : public QueueObject
    {
    public:
        AtomicPriorityQueue() = default;
        THREADPOOL_NO_ALLOWED_COPY(AtomicPriorityQueue)

        HBool tryPop(T& value)
        {
            LOCK_GUARD lock(m_mutex);
            if(m_priority_queue.empty()) {
                return false;
            }
            value = std::move(*m_priority_queue.top());
            m_priority_queue.pop();
            return true;
        }

        HBool tryPop(std::vector<T>& values, int maxPoolBatchSize)
        {
            LOCK_GUARD lock(m_mutex);
            if(m_priority_queue.empty() || maxPoolBatchSize <= 0) {
                return false;
            }

            while(!m_priority_queue.empty() && maxPoolBatchSize--) {
                values.emplace_back(std::move(*m_priority_queue.top()));
                m_priority_queue.pop();
            }

            return true;
        }

        HVoid push(T&& value, int priority)
        {
            std::unique_ptr<T> task(make_unique<T>(std::move(value), priority));
            LOCK_GUARD         lock(m_mutex);
            m_priority_queue.push(std::move(task));
        }

        // HBool empty()const 不能加锁std::lock_guard<std::mutex>;因为const意味着不可更改，所以
        // 没有必要去加锁
        HBool empty()
        {
            LOCK_GUARD lock(m_mutex);
            return m_priority_queue.empty();
        }

    private:
        std::priority_queue<std::unique_ptr<T>> m_priority_queue;
    };

HTHREADPOOL_NAMESPACE_END

#endif
